package org.travelfusion.xmlclient.ri.handler.plane;

import static org.travelfusion.xmlclient.util.TfXAPIUtil.parseDate;

import java.util.HashMap;
import java.util.Map;

import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamReader;

import org.travelfusion.xmlclient.ri.xobject.plane.XFlightSegment;

/**
 * @author Jesse McLaughlin (nzjess@gmail.com)
 * @author Ana Henneberke (ana.henneberke@gmail.com)
 * @author Dogan Narinc (dogan.narinc@gmail.com)
 */
class FlightSegmentSubHandler {

	private final CheckRoutingHandler parent;

	private final Map<String, String> operatorNames = new HashMap<String, String>();

	FlightSegmentSubHandler(CheckRoutingHandler parent) {
		this.parent = parent;
	}

	Map<String, String> getOperatorNames() {
		return operatorNames;
	}

	private static enum State {
		ROOT, //
		ORIGIN, //
		DESTINATION, //
		OPERATOR, //
		FLIGHT_CODE, //
		TRAVEL_CLASS, //
		AIRCRAFT_TYPE
	}

	public XFlightSegment handleResponse() throws Exception {
		XFlightSegment segment = new XFlightSegment();

		StringBuilder builder = new StringBuilder();
		String currentName = null;
		boolean build = false;

		String operatorName = null;

		final XMLStreamReader responseReader = parent.getResponseReader();

		State state = State.ROOT;
		done: for (int event; ((event = responseReader.next()) != XMLStreamConstants.END_DOCUMENT);) {
			switch (event) {
			case XMLStreamConstants.START_ELEMENT:
				currentName = responseReader.getName().getLocalPart();
				builder.setLength(0);
				switch (state) {
				case ROOT:
					if ("Origin".equals(currentName)) {
						state = State.ORIGIN;
						build = true;
					} else if ("Destination".equals(currentName)) {
						state = State.DESTINATION;
						build = true;
					} else if ("DepartDate".equals(currentName)) {
						build = true;
					} else if ("ArriveDate".equals(currentName)) {
						build = true;
					} else if ("Duration".equals(currentName)) {
						build = true;
					} else if ("TfOperator".equals(currentName)) {
						operatorName = null;
						state = State.OPERATOR;
						build = true;
					} else if ("FlightId".equals(currentName)) {
						state = State.FLIGHT_CODE;
						build = true;
					} else if ("TravelClass".equals(currentName)) {
						state = State.TRAVEL_CLASS;
						build = true;
					} else if ("AircraftType".equals(currentName)) {
						state = State.AIRCRAFT_TYPE;
						build = true;
					}
					break;
				}
				break;
			case XMLStreamConstants.CHARACTERS:
				if (build) {
					builder.append(responseReader.getTextCharacters(),
							responseReader.getTextStart(),
							responseReader.getTextLength());
				}
				break;
			case XMLStreamConstants.END_ELEMENT:
				currentName = responseReader.getName().getLocalPart();
				switch (state) {
				case ROOT:
					if ("DepartDate".equals(currentName)) {
						segment.setDepartureTime(parseDate(builder.toString()));
						build = false;
					} else if ("ArriveDate".equals(currentName)) {
						segment.setArrivalTime(parseDate(builder.toString()));
						build = false;
					} else if ("Duration".equals(currentName)) {
						segment.setDuration(Integer.parseInt(builder.toString()));
						build = false;
					} else if ("Segment".equals(currentName)) {
						break done;
					}
					break;
				case ORIGIN:
					if ("Code".equals(currentName)) {
						segment.setOrigin(builder.toString());
					} else if ("Origin".equals(currentName)) {
						state = State.ROOT;
						build = false;
					}
					break;
				case DESTINATION:
					if ("Code".equals(currentName)) {
						segment.setDestination(builder.toString());
					} else if ("Destination".equals(currentName)) {
						state = State.ROOT;
						build = false;
					}
					break;
				case OPERATOR:
					if ("Code".equals(currentName)) {
						segment.setOperator(builder.toString().trim());
						if (segment.getOperator().length() == 0) {
							segment.setOperator(null);
						}
					} else if ("Name".equals(currentName)) {
						operatorName = builder.toString().trim();
					} else if ("TfOperator".equals(currentName)) {
						if (segment.getOperator() != null
								&& operatorName.length() > 0) {
							operatorNames.put(segment.getOperator(),
									operatorName);
						}
						state = State.ROOT;
						build = false;
					}
					break;
				case FLIGHT_CODE:
					if ("Code".equals(currentName)) {
						segment.setCode(builder.toString());
						build = false;
					} else if ("FlightId".equals(currentName)) {
						state = State.ROOT;
						build = false;
					}
					break;
				case TRAVEL_CLASS:
					if ("TfClass".equals(currentName)) {
						segment.setTravelClass(builder.toString());
						build = false;
					} else if ("TravelClass".equals(currentName)) {
						state = State.ROOT;
						build = false;
					}
					break;
				case AIRCRAFT_TYPE:
					if ("AircraftName".equals(currentName)) {
						segment.setAircraftName(builder.toString());
						build = false;
					} else if ("AircraftCode".equals(currentName)) {
						segment.setAircraftCode(builder.toString());
						build = false;
					} else if ("AircraftType".equals(currentName)) {
						state = State.ROOT;
						build = false;
					}
					break;
				}
				break;
			}
		}

		return segment;
	}
}
